﻿using System;
using System.Text;
using System.Windows.Forms;
using ApplicationGenerator.BusinessModule.Elements;
using ApplicationGenerator.BusinessModule.MetaElements;
using ApplicationGenerator.BusinessModule.Interfaces;

namespace ApplicationGenerator.Forms.Forms
{
    public partial class ModelHierarchyTree : UserControl
    {
        private IMetaModel _metaAdapter;

        public IMetaModel MetaAdapter
        {
            set { _metaAdapter = value; }
        }

        public ModelHierarchyTree()
        {
            InitializeComponent();
        }

        public void InitializeTree()
        {
            if (_metaAdapter == null)
            {
                throw new Exception("Należy ustawić model, którego pola mają się wyświetlać na drzewie.");
            }

            TreeNode root = new TreeNode(_metaAdapter.ModelName);
            root.Name = _metaAdapter.ModelName;
            root.Tag = _metaAdapter.ModelName;
            treeModel.Nodes.Add(root);
            AddChildNodes(root, _metaAdapter.ModelName);
        }

        public string GetSelectedField()
        {
            if (treeModel.SelectedNode == null)
            {
                return null;
            }

            StringBuilder pathBuilder = new StringBuilder();
            AddPrefixString(treeModel.SelectedNode, pathBuilder, true);

            return pathBuilder.ToString();
        }

        public bool IsSelectedNode()
        {
            return treeModel.SelectedNode != null;
        }

        private void AddPrefixString(TreeNode actualNode, StringBuilder builder, bool isSelectedNode)
        {
            if (!isSelectedNode)
            {
                builder.Insert(0, ".");
            }

            builder.Insert(0, actualNode.Name);

            if (actualNode.Parent != null && actualNode.Parent.Parent != null && actualNode.Parent.Tag is string)
            {
                builder.Insert(0, (actualNode.Parent.Tag as string) + ".");
            }

            if (actualNode.Parent == null)
            {
                return;
            }

            AddPrefixString(actualNode.Parent, builder, false);
        }

        public Type GetSelectedFieldType()
        {
            if (treeModel.SelectedNode == null)
            {
                return null;
            }

            if (treeModel.SelectedNode.Parent == null || treeModel.SelectedNode.Parent.Tag == null)
            {
                return null;
            }

            string modelName = treeModel.SelectedNode.Parent.Tag as string;
            if (string.IsNullOrEmpty(modelName))
            {
                return null;
            }

            IMetaModel metaAdapter = (new FacadeFactory()).CreateMetaModelFacade().MetaModelCollection[modelName];
            IMetaField metaField = metaAdapter.MetaFieldCollection[treeModel.SelectedNode.Name];

            return metaField.FieldType;
        }

        private void AddChildNodes(TreeNode rootNode, string rootAdapterName)
        {
            IMetaField metaARMField = null;
            IMetaModel rootAdapter = (new FacadeFactory()).CreateMetaModelFacade().MetaModelCollection[rootAdapterName];

            TreeNode nodeChild = null;
            foreach (object metaField in rootAdapter.MetaFieldCollection)
            {
                metaARMField = metaField as IMetaField;
                if (metaARMField == null)
                {
                    throw new Exception("W modelu mogą znajdować się jedynie obiekty typu MetaARMField.");
                }

                nodeChild = new TreeNode();
                nodeChild.Name = metaARMField.FieldName;
                nodeChild.Text = metaARMField.FieldName;

                // dla relacji i list zapamiętujemy MetaARMAdapter
                if (metaARMField.MetaFieldType == MetaFieldType.Relation)
                {
                    // nazwa modelu 
                    nodeChild.Tag = metaARMField.FieldType.Name;
                }

                if (metaARMField.MetaFieldType == MetaFieldType.List)
                {
                    nodeChild.Tag = metaARMField.FieldType.GetGenericArguments()[0].Name;
                }

                rootNode.Nodes.Add(nodeChild);
            }
        }

        private void treeModel_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            TreeView treeView = sender as TreeView;
            TreeNode treeNode = treeView.SelectedNode;
            if (treeNode == null || treeNode.Tag == null || treeNode.Nodes.Count > 0)
            {
                return;
            }

            string modelName = treeNode.Tag as string;
            if (!string.IsNullOrEmpty(modelName))
            {
                AddChildNodes(treeNode, modelName);
            }
        }
    }


}
